package com.edaoe.kit.lucene;



import com.hankcs.lucene.HanLPAnalyzer;
import com.jfinal.kit.PropKit;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class IndexManager {
    private static final String INDEX_PATH= PropKit.get("lucenePath");
    private static final Analyzer ANALYZER=new HanLPAnalyzer();
    private static Map<String,IndexWriter> indexWriterMap=new HashMap<>();
    private static Map<String,IndexSearcher> indexSearcherMap=new HashMap<>();
    private static final QueryParser PARSER = new QueryParser("text", ANALYZER);

    private static IndexWriter getIndexWriter(String indexName){
        if (indexWriterMap.get(indexName)!=null)
            return indexWriterMap.get(indexName);
        try {
            Directory directory = FSDirectory.open( Paths.get( INDEX_PATH+ File.separator+indexName ) );
            IndexWriterConfig indexWriterConfig=new IndexWriterConfig(ANALYZER);
            IndexWriter indexWriter=new IndexWriter(directory,indexWriterConfig);
            indexWriterMap.put(indexName,indexWriter);
            return indexWriter;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static IndexSearcher getIndexSearcher(String indexName){
        if (indexSearcherMap.get(indexName)!=null)
            return indexSearcherMap.get(indexName);
        try {
            Directory directory = FSDirectory.open( Paths.get( INDEX_PATH+ File.separator+indexName ) );
            IndexReader indexReader= DirectoryReader.open(directory);
            IndexSearcher indexSearcher=new IndexSearcher(indexReader);
            indexSearcherMap.put(indexName,indexSearcher);
            return indexSearcher;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void rebuildIndexSearcher(String indexName){
        try {
            indexSearcherMap.remove(indexName);
            Directory directory = FSDirectory.open( Paths.get( INDEX_PATH+ File.separator+indexName ) );
            IndexReader indexReader= DirectoryReader.open(directory);
            IndexSearcher indexSearcher=new IndexSearcher(indexReader);
            indexSearcherMap.put(indexName,indexSearcher);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 增加索引
     */
    public static boolean addDocument(String indexName,Document doc) {
        try {
            IndexWriter indexWriter=getIndexWriter(indexName);
            indexWriter.addDocument(doc);
            indexWriter.commit();
            rebuildIndexSearcher(indexName);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 删除索引
     */
    public static boolean deleteDocuments(String indexName,Term term) {
        try {
            IndexWriter indexWriter=getIndexWriter(indexName);
            indexWriter.deleteDocuments(term);
            indexWriter.commit();
            rebuildIndexSearcher(indexName);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 删除所有索引
     */
    public static boolean deleteAll(String indexName) {
        try {
            IndexWriter indexWriter=getIndexWriter(indexName);
            indexWriter.deleteAll();
            indexWriter.commit();
            rebuildIndexSearcher(indexName);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 更新索引
     */
    public static boolean updateDocument(String indexName,Term term, Document doc) {
        try {
            IndexWriter indexWriter=getIndexWriter(indexName);
            indexWriter.updateDocument(term, doc);
            indexWriter.commit();
            rebuildIndexSearcher(indexName);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static SearchResult search(String indexName,String keywords, int pageNumber, int pageSize){
        int start=(pageNumber-1)*pageSize;
        int end=start+pageSize;
        SearchResult result = new SearchResult();
        List<Document> docs = new ArrayList<>();
        result.setDocuments(docs);
        IndexSearcher indexSearcher = getIndexSearcher(indexName);
        try {
            Query query = PARSER.parse(keywords);
            TopDocs topDocs = indexSearcher.search(query, end);
            result.setCount(topDocs.totalHits);
            end = end > topDocs.totalHits ? topDocs.totalHits : end;
            for (int i = start; i < end; i++) {
                docs.add(indexSearcher.doc(topDocs.scoreDocs[i].doc));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}
